package socket

import (
	"fmt"
	"iot-base/auth/db"
	"iot-base/auth/types"
	"iot-base/auth/utils"
	"sync"
)

var IoRoom *Rooms

func init() {
	IoRoom = newRooms()
}

func newRooms() *Rooms {
	return &Rooms{
		roomMap: make(map[string]map[int64]interface{}),
	}
}

type Rooms struct {
	roomMap map[string]map[int64]interface{}
	rw      sync.RWMutex
}

func (h *Rooms) AddRoom(roomName string, userId int64) {
	h.rw.Lock()
	defer h.rw.Unlock()
	if _, ok := h.roomMap[roomName]; !ok {
		h.roomMap[roomName] = make(map[int64]interface{})
	}
	h.roomMap[roomName][userId] = 1

}

func (h *Rooms) ExitRoom(roomName string, userId int64) {
	h.rw.Lock()
	defer h.rw.Unlock()
	if _, ok := h.roomMap[roomName][userId]; ok {
		delete(h.roomMap[roomName], userId)
	}
}

func (h *Rooms) ExitAllRoom(userId int64) {
	h.rw.Lock()
	defer h.rw.Unlock()
	for key, _ := range h.roomMap {
		if _, ok := h.roomMap[key][userId]; ok {
			delete(h.roomMap[key], userId)
		}
	}
}

func (h *Rooms) GetRoomUser(rooName string) []int64 {
	h.rw.RLock()
	defer h.rw.RUnlock()
	values, ok := h.roomMap[rooName]
	if !ok {
		return []int64{}
	}
	result := make([]int64, 0, len(values))
	for k, _ := range values {
		result = append(result, k)
	}
	return append([]int64{}, result...)
}

func (h *Rooms) PushAlarmMsg(rooName string, event string, msg types.RespAlarm) {
	redis := db.NewRedis()
	var incr int64 = 1
	if msg.Flag == "END" {
		incr = -1
	}
	resp := types.NewSocketIoResult()
	userIds := h.GetRoomUser(rooName)
	for _, v := range userIds {
		// alarm msg num
		key := fmt.Sprintf("%s#%v", db.KeyAlarmTotal, v)
		num, _ := redis.IncrBy(key, incr)
		sendMsg := make(map[int64]SocketMsg)
		sendMsg[v] = SocketMsg{
			Event: event,
			Msg:   resp.Success(utils.H{"alarm_total": num, "info": msg}, ""),
		}
		Manager.UidBroadcast <- sendMsg
	}
}

func (h *Rooms) PushMsg(rooName string, event string, msg interface{}) {
	resp := types.NewSocketIoResult()
	userIds := h.GetRoomUser(rooName)
	for _, v := range userIds {
		sendMsg := make(map[int64]SocketMsg)
		sendMsg[v] = SocketMsg{
			Event: event,
			Msg:   resp.Success(msg, ""),
		}
		Manager.UidBroadcast <- sendMsg
	}
}
